// tube_detector.dart
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'tube_detector_bindings.dart';

/// 试管检测器类
/// 提供高级API来操作原生试管检测功能
class TubeDetector {
  Pointer<Void> _nativeDetector;

  ///< 指向原生检测器实例的指针
  bool _isInitialized = false;

  ///< 检测器是否已初始化

  /// 构造函数
  /// 创建原生检测器实例
  TubeDetector() : _nativeDetector = TubeDetectorBindings.createTubeDetector() {
    if (_nativeDetector == nullptr) {
      throw Exception('Failed to create tube detector');

      ///< 创建失败时抛出异常
    }
  }

  /// 初始化检测器
  /// @param cameraIndex 摄像头设备索引（默认0）
  /// @return 初始化是否成功
  bool initialize({int cameraIndex = 0}) {
    _isInitialized =
        TubeDetectorBindings.initializeDetector(_nativeDetector, cameraIndex);
    return _isInitialized;
  }

  /// 开始检测流程
  /// @return 启动是否成功
  /// @throws Exception 如果检测器未初始化
  bool startDetection() {
    if (!_isInitialized) {
      throw Exception('Detector not initialized');

      ///< 未初始化时抛出异常
    }
    return TubeDetectorBindings.startDetection(_nativeDetector);
  }

  /// 停止检测流程
  void stopDetection() {
    TubeDetectorBindings.stopDetection(_nativeDetector);
  }

  /// 处理单帧图像
  /// @return 检测结果
  /// @throws Exception 如果检测器未初始化或处理失败
  DetectionResult processSingleFrame() {
    if (!_isInitialized) {
      throw Exception('Detector not initialized');

      ///< 未初始化时抛出异常
    }

    // 调用原生函数处理单帧图像
    final resultPtr = TubeDetectorBindings.processSingleFrame(_nativeDetector);
    if (resultPtr == nullptr) {
      throw Exception('Failed to process frame');

      ///< 处理失败时抛出异常
    }

    // 转换检测结果为Dart对象
    final result = _convertDetectionResult(resultPtr);

    // 释放原生内存
    TubeDetectorBindings.freeDetectionResult(resultPtr);

    return result;
  }

  /// 获取当前试管状态
  /// @return 试管状态列表
  List<TubeLocation> getCurrentTubeStates() {
    // 分配内存用于接收数量
    final countPtr = calloc<Int32>();

    // 调用原生函数获取试管状态
    final statesPtr =
        TubeDetectorBindings.getCurrentTubeStates(_nativeDetector, countPtr);

    if (statesPtr == nullptr) {
      calloc.free(countPtr);

      ///< 释放内存
      return [];

      ///< 获取失败返回空列表
    }

    final count = countPtr.value;
    final states = _convertTubeLocations(statesPtr, count);

    // 释放原生内存
    TubeDetectorBindings.freeTubeStates(statesPtr);
    calloc.free(countPtr);

    return states;
  }

  /// 设置调试模式
  /// @param enable 是否启用调试模式
  void setDebugMode(bool enable) {
    TubeDetectorBindings.setDebugMode(_nativeDetector, enable);
  }

  // =========================================================================
  // 私有辅助方法
  // =========================================================================

  /// 转换检测结果从原生格式到Dart格式
  /// @param resultPtr 指向原生检测结果的指针
  /// @return Dart格式的检测结果
  DetectionResult _convertDetectionResult(
      Pointer<DetectionResultFFI> resultPtr) {
    final result = resultPtr.ref;

    return DetectionResult(
      rectangles:
          _convertTubeLocations(result.rectangles, result.rectanglesCount),
      circles: _convertTubeLocations(result.circles, result.circlesCount),
      sortedTubes:
          _convertTubeLocations(result.sortedTubes, result.sortedTubesCount),
      tubeMatches:
          _convertIntArray(result.tubeMatches, result.tubeMatchesCount),
      tubesWithTube: _convertTubeLocations(
          result.tubesWithTube, result.tubesWithTubeCount),
    );
  }

  /// 转换试管位置数组从原生格式到Dart格式
  /// @param ptr 指向原生试管位置数组的指针
  /// @param count 数组元素数量
  /// @return Dart格式的试管位置列表
  List<TubeLocation> _convertTubeLocations(
      Pointer<TubeLocationFFI> ptr, int count) {
    final locations = <TubeLocation>[];

    // 遍历原生数组并转换为Dart对象
    for (int i = 0; i < count; i++) {
      final locationPtr = ptr.elementAt(i);
      final location = locationPtr.ref;

      locations.add(TubeLocation(
        x: location.x,
        y: location.y,
        index: location.index,
        hasTube: location.hasTube,
      ));
    }

    return locations;
  }

  /// 转换整数数组从原生格式到Dart格式
  /// @param ptr 指向原生整数数组的指针
  /// @param count 数组元素数量
  /// @return Dart格式的整数列表
  List<int> _convertIntArray(Pointer<Int32> ptr, int count) {
    final list = <int>[];

    // 遍历原生数组并转换为Dart列表
    for (int i = 0; i < count; i++) {
      list.add(ptr.elementAt(i).value);
    }

    return list;
  }

  /// 释放资源
  /// 销毁原生检测器实例
  void dispose() {
    if (_nativeDetector != nullptr) {
      TubeDetectorBindings.destroyTubeDetector(_nativeDetector);
      _nativeDetector = nullptr;

      ///< 将指针设为nullptr避免重复释放
    }
  }

  /// 析构函数
  /// 确保资源被正确释放
  @override
  void finalize() {
    dispose();
  }
}
